"""
1 为什么进行特征预处理？
已经是可以被计算机理解的特征数据，但是为了能够更好训练出更好的模型，
通过一些转换函数将特征数据转换成更加适合算法模型的特征数据过程

2 为什么我们要进行特征预处理：归⼀化/标准化？
特征的单位或者⼤⼩相差较⼤，或者某特征的⽅差相⽐其他的特征要⼤出⼏个数量级，容易影响（⽀配）⽬标 结果，使得⼀些算法⽆法学习到其它的特征

一般用标准化，因为如果特征数据中有异常数据归一化的计算结果影响比较大。

原始数据：milage特征比其他特征大几个数量级
   milage    Liters  Consumtime
   40920   8.326976    0.953952
   14488   7.153469    1.673904
   26052   1.441871    0.805124
   75136  13.147394    0.428964
   38344   1.669788    0.134296

归一化后：

[[0.43582641 0.58819286 0.53237967]
 [0.         0.48794044 1.        ]
 [0.19067405 0.         0.43571351]
 [1.         1.         0.19139157]
 [0.3933518  0.01947089 0.        ]]

3 什么时候要进行特征预处理 归一化或标准化？
 特征之间的单位或者⼤⼩相差较⼤，或者某特征的⽅差相⽐其他的特征要⼤出⼏个数量级，容易影响（⽀配）⽬标 结果，削弱其他特征的影响。

4 归一化和标准化选择

归一化主要是将特征值缩放到一个特定的范围，比如[0,1]或[-1,1]。当特征的取值范围差异很大时，归一化可以帮助算法更快地收敛。
此外，一些算法如支持向量机（SVM）和神经网络对输入特征的尺度敏感，因此需要进行归一化。

标准化则是通过调整特征的均值和标准差，使得处理后的特征符合标准正态分布，即均值为0，标准差为1。
当特征中存在异常值或噪声，或者特征的分布不是正态分布时，标准化通常是一个更好的选择。标准化可以间接通过中心化避免异常值和极端值的影响。

在实际应用中，选择归一化还是标准化取决于数据的特性和所使用的算法。如果数据较为稳定，不存在极端的最大最小值，并且算法对输入特征的尺度不敏感，那么可以选择归一化。
如果数据存在异常值和较多噪音，或者算法对输入特征的分布有特定要求（如要求是正态分布），那么应该选择标准化。
"""

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
def minmax_pro():
    """
    归一化
    通过对原始数据进⾏变换把数据映射到(默认为[0,1])之间
    :return:
    """
    data = pd.read_csv("./dating.txt")
    # 每行都要 列只要前3列
    data = data.iloc[:, :3]

    print(data)

    transfer = MinMaxScaler(feature_range=(0, 1))
    processed_data = transfer.fit_transform(data)

    print(processed_data)
    return None

from sklearn.preprocessing import StandardScaler
def stand_pro():
    """
    标准化
    新x = (旧x - 均值) / 标准差
    transfer.fit_transform(data)：
        分为两步 fit计算均值和标准差 transform套用公式 新x = (旧x - 均值) / 标准差 将数据转换
    :return:
    """
    data = pd.read_csv("./dating.txt")
    # 每行都要 列只要前3列
    data = data.iloc[:, :3]

    transfer = StandardScaler()
    processed_data = transfer.fit_transform(data)

    print("标准化处理前的结果\n", data)
    print("标准化处理后的结果\n", processed_data)
    print("每一列的方差为：\n", transfer.var_)
    print("每一列的均值：\n", transfer.mean_)
    return None

if __name__ == '__main__':
    # minmax_pro()

    stand_pro()